package processor;

import annotation.ConfigValue;
import annotation.LazyAutowire;
import bean.QueryTemplate;
import com.convertlab.multitenancy.CurrentTenantThreadLocal;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

/**
 * @author jiang
 */
@Component
public class ConfigValueProcessor implements AnnotationProcessor<ConfigValue> {

    @LazyAutowire
    private CurrentTenantThreadLocal currentTenantThreadLocal;

    @LazyAutowire
    private QueryTemplate queryTemplate;

    @Override
    public Class<ConfigValue> targetAnnotation() {
        return ConfigValue.class;
    }

    @Override
    public void classInit(Class<ConfigValue> configValue, Object bean) {

    }

    @Override
    public void fieldInit(Class<ConfigValue> configValue, Object bean, Field field, Object o) {
        ConfigValue annotation = AnnotationUtils.findAnnotation(field, configValue);
        if (queryTemplate != null) {
            //language=MySQL
            String sql = "SELECT `value` FROM wechat_corp_dictionary WHERE mark = ? AND `key` = ? AND status = 1 " +
                    (currentTenantThreadLocal.get() != null ? "AND tenant_id = " + currentTenantThreadLocal.get() : "");
            String value = queryTemplate.queryForObject(sql, String.class, annotation.mark(), annotation.key());
            if (!annotation.clazz().getName().contains("java.lang.String") && (field.getType().isAssignableFrom(annotation.clazz()) || field.getType().getName().contains("java.lang.Object"))) {
                ObjectMapper mapper = new ObjectMapper();
                try {
                    Object object = mapper.readValue(value, annotation.clazz());
                    field.setAccessible(true);
                    field.set(bean, object);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else if (annotation.clazz().getName().contains("java.lang.String")) {
                try {
                    field.setAccessible(true);
                    field.set(bean, value);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void methodBefore(Class<ConfigValue> configValue, Object bean, Method method, Object[] parameters) {

    }

    @Override
    public Object methodAfter(Class<ConfigValue> configValue, Object bean, Method method, Object ret) {
        return ret;
    }

    @Override
    public Object parameterInit(Class<ConfigValue> a, Object bean, Method method, Parameter parameter, Object o) {
        ConfigValue annotation = AnnotationUtils.findAnnotation(parameter, a);
        if (queryTemplate != null) {
            String sql = "SELECT `value` FROM wechat_corp_dictionary WHERE mark = ? AND `key` = ? AND status = 1 " +
                    (currentTenantThreadLocal.get() != null ? "AND tenant_id = " + currentTenantThreadLocal.get() : "");
            String value = queryTemplate.queryForObject(sql, String.class, annotation.mark(), annotation.key());
            if (!annotation.clazz().getName().contains("java.lang.String") && (parameter.getType().isAssignableFrom(annotation.clazz()) || parameter.getType().getName().contains("java.lang.Object"))) {
                ObjectMapper mapper = new ObjectMapper();
                try {
                    Object object = mapper.readValue(value, annotation.clazz());
                    return object;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else if (annotation.clazz().getName().contains("java.lang.String")) {
                return value;
            }
        }
        return o;
    }
}

